﻿using System;
using System.Collections.Generic;
using System.Text;

namespace EGConfig
{
    public interface IConfigClassTemplate
    {
        public string ClassText(string className, string classFiled);

        public string FiledName(string filedName, ConfigType filedType);
    }

    public interface IConfigTableTemplate
    {
        public void SetConfigData(ConfigData data);
        public string FiledName(string filedName, int indentation);
        public string FiledValue(string filedValue, ConfigType filedType, int indentation);
        public string FiledNameLinkValue(string filedName, string filedValue);
        public string FiledCombine(int rowIndex, List<string> filedList, int indentation);
        public string DataCombine(List<string> dataList);
    }

    public class CSharpClassTemplate : IConfigClassTemplate
    {
        public string ClassText(string className, string classFiled)
        {
            return $"using System.Collections.Generic;\n\npublic class {className}\n{{\n{classFiled}\n}}";
        }

        public string FiledName(string filedName, ConfigType filedType)
        {
            return $"public {filedType.ToStringType()} {ExcelUtil.ToFirstUpper(filedName)};";
        }
    }

    public class JsonTableTemplate : IConfigTableTemplate
    {
        private ConfigData data;

        public void SetConfigData(ConfigData data)
        {
            this.data = data;
        }

        public string FiledName(string filedName, int indentation)
        {
            StringBuilder stringBuilder = new StringBuilder();
            ExcelUtil.AddIndentation(stringBuilder, indentation, 2);
            stringBuilder.Append($"\"{ExcelUtil.ToFirstLower(filedName)}\"");
            return stringBuilder.ToString();
        }

        public string FiledValue(string filedValue, ConfigType filedType, int indentation)
        {
            StringBuilder stringBuilder = new StringBuilder();
            switch (filedType.MainType)
            {
                case EConfigType.Int:
                case EConfigType.Long:
                case EConfigType.Float:
                case EConfigType.Double:
                {
                    if (filedValue == null)
                    {
                        stringBuilder.Append("0");
                    }
                    else
                    {
                        stringBuilder.Append(filedValue);
                    }

                    break;
                }
                case EConfigType.String:
                {
                    if (filedValue == null)
                    {
                        stringBuilder.Append($"null");
                    }
                    else
                    {
                        stringBuilder.Append($"\"{filedValue}\"");
                    }

                    break;
                }
                case EConfigType.List:
                {
                    if (filedValue == null)
                    {
                        stringBuilder.Append("[]");
                        break;
                    }

                    stringBuilder.Append("[\n");
                    string[] itemArr = filedValue.Split(',');
                    for (int i = 0; i < itemArr.Length; i++)
                    {
                        string itemValue = FiledValue(itemArr[i], filedType.SubType1, 0);
                        ExcelUtil.AddIndentation(stringBuilder, indentation + 1, 2);
                        stringBuilder.Append(itemValue);
                        if (i < itemArr.Length - 1)
                        {
                            stringBuilder.Append(",");
                        }

                        stringBuilder.Append("\n");
                    }

                    ExcelUtil.AddIndentation(stringBuilder, indentation, 2);
                    stringBuilder.Append("]");
                    break;
                }
                case EConfigType.Dictionary:
                {
                    break;
                }
                default:
                    throw new Exception($"{filedType.MainType}:无法解析的类型");
            }

            return stringBuilder.ToString();
        }

        public string FiledNameLinkValue(string filedName, string filedValue)
        {
            return $"{filedName}: {filedValue}";
        }

        public string FiledCombine(int rowIndex, List<string> filedList, int indentation)
        {
            StringBuilder stringBuilder = new StringBuilder();
            ExcelUtil.AddIndentation(stringBuilder, indentation, 2);
            stringBuilder.Append("{\n");
            for (int i = 0; i < filedList.Count; i++)
            {
                stringBuilder.Append(filedList[i]);
                if (i < filedList.Count - 1)
                {
                    stringBuilder.Append(",");
                }

                stringBuilder.Append("\n");
            }

            ExcelUtil.AddIndentation(stringBuilder, indentation, 2);
            stringBuilder.Append("}");

            return stringBuilder.ToString();
        }

        public string DataCombine(List<string> dataList)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append("[\n");
            for (int i = 0; i < dataList.Count; i++)
            {
                stringBuilder.Append(dataList[i]);
                if (i < dataList.Count - 1)
                {
                    stringBuilder.Append(",");
                }

                stringBuilder.Append("\n");
            }

            stringBuilder.Append("]");

            return stringBuilder.ToString();
        }
    }

    public class LuaTableTemplate : IConfigTableTemplate
    {
        private ConfigData data;

        public void SetConfigData(ConfigData data)
        {
            this.data = data;
        }

        public string FiledName(string filedName, int indentation)
        {
            StringBuilder stringBuilder = new StringBuilder();
            ExcelUtil.AddIndentation(stringBuilder, indentation, 4);
            stringBuilder.Append($"{ExcelUtil.ToFirstLower(filedName)}");
            return stringBuilder.ToString();
        }

        public string FiledValue(string filedValue, ConfigType filedType, int indentation)
        {
            StringBuilder stringBuilder = new StringBuilder();
            switch (filedType.MainType)
            {
                case EConfigType.Int:
                case EConfigType.Long:
                case EConfigType.Float:
                case EConfigType.Double:
                {
                    if (filedValue == null)
                    {
                        stringBuilder.Append(("nil"));
                        break;
                    }

                    stringBuilder.Append(filedValue);
                    break;
                }
                case EConfigType.String:
                {
                    if (filedValue == null)
                    {
                        // stringBuilder.Append(("nil"));
                        stringBuilder.Append(("\"\""));
                        break;
                    }

                    stringBuilder.Append($"\"{filedValue}\"");
                    break;
                }
                case EConfigType.List:
                {
                    if (filedValue == null)
                    {
                        stringBuilder.Append(("nil"));
                        break;
                    }

                    stringBuilder.Append("{\n");
                    string[] itemArr = filedValue.Split(',');
                    for (int i = 0; i < itemArr.Length; i++)
                    {
                        string itemValue = FiledValue(itemArr[i], filedType.SubType1, 0);
                        ExcelUtil.AddIndentation(stringBuilder, indentation + 1, 4);
                        stringBuilder.Append(itemValue);
                        if (i < itemArr.Length - 1)
                        {
                            stringBuilder.Append(",");
                        }

                        stringBuilder.Append("\n");
                    }

                    ExcelUtil.AddIndentation(stringBuilder, indentation, 4);
                    stringBuilder.Append("}");
                    break;
                }
                case EConfigType.Dictionary:
                {
                    break;
                }
                default:
                    throw new Exception($"{filedType.MainType}:无法解析的类型");
            }

            return stringBuilder.ToString();
        }

        public string FiledNameLinkValue(string filedName, string filedValue)
        {
            return $"{filedName} = {filedValue}";
        }

        public string FiledCombine(int rowIndex, List<string> filedList, int indentation)
        {
            StringBuilder stringBuilder = new StringBuilder();
            ExcelUtil.AddIndentation(stringBuilder, indentation, 4);
            if (data.mainIndex!=-1)
            {
                stringBuilder.Append(
                    $"[{FiledValue(data.values[rowIndex][data.mainIndex], data.propertyTypes[data.mainIndex], 0)}] = {{\n");
            }
            else
            {
                stringBuilder.Append($"{{\n");
            }
            for (int i = 0; i < filedList.Count; i++)
            {
                stringBuilder.Append(filedList[i]);
                if (i < filedList.Count - 1)
                {
                    stringBuilder.Append(",");
                }

                stringBuilder.Append("\n");
            }

            ExcelUtil.AddIndentation(stringBuilder, indentation, 4);
            stringBuilder.Append("}");

            return stringBuilder.ToString();
        }

        private string TypeConvert(ConfigType type)
        {
            switch (type.MainType)
            {
                case EConfigType.Int:
                case EConfigType.Long:
                case EConfigType.Float:
                case EConfigType.Double:
                {
                    return "number";
                }
                case EConfigType.String:
                {
                    return "string";
                }
                case EConfigType.List:
                {
                    string subType = TypeConvert(type.SubType1);
                    return $"{subType}[]";
                }
                default:
                    return null;
            }
        }

        public string DataCombine(List<string> dataList)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append($"---@class {data.upperName}\n");
            for (int i = 0; i < data.propertyNames.Count; i++)
            {
                string pName = data.propertyNames[i];
                string pTips = data.propertyTips[i];
                string pType = TypeConvert(data.propertyTypes[i]);
                stringBuilder.Append($"---@field {FiledName(pName, 0)} {pType} {pTips}\n");
            }

            stringBuilder.Append($"local classDef = nil\n");
            stringBuilder.Append($"---@type {data.upperName}[]\n");

            stringBuilder.Append("local config = {\n");
            for (int i = 0; i < dataList.Count; i++)
            {
                stringBuilder.Append(dataList[i]);
                if (i < dataList.Count - 1)
                {
                    stringBuilder.Append(",");
                }

                stringBuilder.Append("\n");
            }

            stringBuilder.Append("}\nreturn config");

            return stringBuilder.ToString();
        }
    }
}